# -*- coding:utf-8 -*-
from gohttp import *
from tlogger import logger
import ConfigParser
import urllib
import json

conf = ConfigParser.ConfigParser()
conf.read('config.ini')
cf = conf
log = logger('api.log', cf.get('global', 'log_level'))

def add_phy_flow(flow_name, netunit_name, out_if_name):
    """
    :param flow_name:   flow name
    :param netunit_name:  netunit name ,must have two "_" to be split()
    :param out_if_name:   FULL physic interface name
    :return:  None is successful;  -1 is failed
    """
    try:
        slot_num = netunit_name.split('_')[1]
        index= netunit_name.split('_')[2]
    except:
        log.error("Error invalid netunit_name: %s"%netunit_name)
        return -1
    data = {"@pagepath":"flow_policy/0","@ot":"add", "id":"0",
            "slot_num":slot_num, "index":index, "type":"0", "net":"0",
            "name":flow_name, "out_inf":out_if_name, "netunit":netunit_name}
    url = 'http://' + cf.get('global', 'dutip') + cf.get('add_phy_flow', 'url')
    headers = build_http_header()
    res = basic_http_post(url, urllib.urlencode(data), headers)
    if res:
        temp_res = error_handle('add_phy_flow', res)
        if temp_res:
            if temp_res == 'OK':
                log.info('Add physic flow successful! %s %s %s '%(flow_name, netunit_name, out_if_name))
            else:
                log.warn('Add physic flow failed %s %s %s\n%s'%(flow_name, netunit_name,
                                                                out_if_name, temp_res))
                return -1
        else:
            log.error('Add physic flow failed!, UNKNOW information \n%s'%res)
            return -1
    else:
        log.error('Add physic flow, sent request, but can not receive valid data!')
        return -1

def add_vir_flow(flow_name, netunit1, inf1, netunit2, inf2):
    """
    :param flow_name:   flow name
    :param netunit1:   netunit name ,must have two "_" to be split()
    :param inf1:     interface name like abc, without xge_ as prefix
    :param netunit2:  netunit name ,must have two "_" to be split()
    :param inf2:     interface name like abc, without xge_ as prefix
    :return:   None is successful;  -1 is failed
    """
    try:
        slot_num1 = netunit1.split('_')[1]
        index1 = netunit1.split('_')[2]
        slot_num2 = netunit2.split('_')[1]
        index2 = netunit2.split('_')[2]
    except:
        log.error("Error invalid netunit_name : %s or %s"%(netunit1, netunit2))
        return -1
    data = {"@pagepath":"flow_policy/0","@ot":"add", "id":"0",
            "slot_num1":slot_num1, "slot_num2":slot_num2, "index1":index1, "index2":index2,
            "type":"1", "net":"0", "name":flow_name,
            "netunit1":netunit1, "inf1":inf1,
            "netunit2":netunit2, "inf2":inf2}
    url = 'http://' + cf.get('global', 'dutip') + cf.get('add_vir_flow', 'url')
    headers = build_http_header()
    res = basic_http_post(url, urllib.urlencode(data), headers)
    if res:
        temp_res = error_handle('add_vir_flow', res)
        if temp_res:
            if temp_res == 'OK':
                log.info('Add virtual flow successful! %s %s %s %s %s'%(flow_name, netunit1,
                                                                        inf1, netunit2, inf2))
            else:
                log.warn('Add virtual flow failed %s %s %s %s %s\n%s' % (flow_name, netunit1,
                                                                        inf1, netunit2, inf2, temp_res))
                return -1
        else:
            log.error('Add virtual flow failed!, Unknown information \n%s' % res)
            return -1
    else:
        log.error('Add virtual flow, sent request, but can not receive valid data!')
        return -1

def del_flow(pvid):
    data = urllib.urlencode({"cn":"流定义", "pf":"flow_policy", "desc":"name", "pv":pvid})
    url = 'http://' + cf.get('global', 'dutip') + cf.get('del_flow', 'url')
    headers = build_http_header()
    log.debug("del_flow(%s)"%pvid)
    return basic_http_get(url, data, headers)

def list_flow():
    """
    :return: successful: a list of flow information
             failed: None
    """
    url = 'http://' + cf.get('global', 'dutip') + cf.get('list_flow', 'url')
    headers = build_http_header()
    res = basic_http_get(url, http_headers=headers)
    if not res:
        log.warn("list_flow() sent request, but receive nothing!")
        return
    if res.find('Content-type: application/json') !=-1:
        #res_header = res.split('\r\n\r\n')[0]
        res_body = res.split('\r\n\r\n')[1]
        try:
            flist = json.loads(res_body)["data"]
        except:
            log.warn("Error: when list_flow(), get un-json-file:\n%s"%res_body)
            return
        log.debug('list_flow() Get FLOW LIST: \n%s'%flist)
        return flist
    else:
        log.warn("list_flow() Error: sent request, but get this! \n%s"%res)
        return

def get_flow_id_by_name(name):
    """
    :param name:  flow name
    :return:  successful: a list of flow id
              failed: None or []
    """
    info = get_flow_info_by_name(name)
    if info:
        id = []
        for i in info:
            if i.get('name') == name:
                id.append(i.get('id'))
        if not id:
            log.warn("get_flow_id_by_name(%s) Not Found "%name)
        else:
            log.info("get_flow_id_by_name(%s) get ids: \n%s" %(name, id))
            return id

def get_flow_id_by_names(names):
    """
    :param names:  flow names , must be a list like ['flow_a']
    :return: successful: a list of ids like this ['2', '5']
             failed: None
    """
    content = list_flow()
    if content:
        flow_ids = []
        for n in names:
            for d in content:
                if d.get('name') == n:
                    flow_ids.append(d.get('id'))
        if not flow_ids:
            log.warn("get_flow_id_by_names(%s) Not Found: %s" %(names, names))
        else:
            return flow_ids

def get_flow_info_by_name(name):
    """
    :param name: flow name
    :return:  successful: a list of flow info
              failed: None
    """
    content = list_flow()
    if content != -1:
        flow_info = []
        for d in content:
            if d.get('name') == name:
                flow_info.append(d)
        if not flow_info:
            log.warn("get_flow_info_by_name(%s) Not Found" % name)
            return
        else:
            return flow_info

def get_flow_info_by_id(id):
    """
    :param id: flow id
    :return: successufl: a flow info
             failed: None
    """
    content = list_flow()
    if content:
        for d in content:
            if d.get('id') == str(id):
                return d

def get_flow_info_by_ids(*id):
    """
    :param id: multi params, can be : '1', '8', '10' ...
    :return: successufl: a list of flows info
             failed: None or []
    """
    content = list_flow()
    if content:
        flow_info_list = []
        for d in id:
            for i in content:
                if i.get('id') == str(d):
                    flow_info_list.append(i)
        if flow_info_list:
            log.info("get_flow_info_by_ids(*id) get flows: \n%s"%flow_info_list)
            return flow_info_list


def build_http_header():
    header = {}
    for h in cf.options('http_global_header'):
        header['-'.join([i.capitalize() for i in h.split('-')])] = cf.get('http_global_header', h)
    return header

def error_handle(fuc_name, data):
    """
    :param fuc_name:   function name, mapping the config.ini sections
    :param data:    string data used for judging which error occur
    :return: return the error reason, None is unknown error information
    """
    error_info = cf.get(fuc_name, 'error_info')
    right_info = cf.get(fuc_name, 'right_info')
    data = repr(data)
    if error_info and right_info:
        try:
            info = json.loads(error_info)
            for k, v in info.items():
                if data.find(k)!=-1:
                    return v
            r_info = json.loads(right_info)
            for k, v in r_info.items():
                if data.find(k)!=-1:
                    return "OK"
            log.warn("Unknown response when run %s(): \n%s"%(fuc_name, data))
            return
        except Exception, e:
            log.error('Error :check config.ini error_info --(must be json) \n%s'%e)
            return
    else:
        log.error('Warn: %s not be supported!'%fuc_name)
        return

if __name__ == "__main__":
    #add_vir_flow('abc1', 'FW_1_1', 'ADC12', 'ADC_1_2', 'fw11')
    #get_flow_info_by_ids('6', '7')
    add_phy_flow('abbb', 'WAF_2_2', 'xge2/0')

